﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Engine;
using SharpDX;
using SharpDX.D3DCompiler;
using SharpDX.Direct3D11;
using SharpDX.Direct3D;
using SharpDX.DXGI;
using SharpDX.Windows;
using SharpDX.DirectInput;
using SharpDX.Multimedia;
using SharpDX.RawInput;
using Device = SharpDX.Direct3D11.Device;
using Resource = SharpDX.Direct3D11.Resource;

namespace Engine
{
    public class GameObject
    {
        public DVector3 Position;

        public DVector3 AABBMax;
        public DVector3 AABBMin;

        public DVector3 LocalAABBMax;
        public DVector3 LocalAABBMin;

        public DMatrix Transformation;

        public MultiMeshContainer MMC;

        private DVector3[] TL = new DVector3[8];

        public int StartSplit = 0;
        public int StopSplit = 0;

        TextureContainer Lens;
        DVector3[] EngPosition;

        public GameObject(string MeshName)
        {
            Position = new DVector3();

            MMC = ContentManager.LoadMultiMesh(MeshName);
            LocalAABBMin = Conversion.ToDoubleVector(MMC.LocalAABBMin);
            LocalAABBMax = Conversion.ToDoubleVector(MMC.LocalAABBMax);

            Transformation =  DMatrix.CreateScale(1d)*DMatrix.CreateTranslation(Position) * DMatrix.CreateFromYawPitchRoll(0, 0, 0);

            RecalcAABB();

            InitObj();
            Lens = ContentManager.LoadTexture2D("Content/Textures/Lens");

        }

        public void TempSetPos(DVector3 Pos)
        {
            Position = Pos;
            Transformation = DMatrix.CreateScale(1d) * DMatrix.CreateTranslation(Position) * DMatrix.CreateFromYawPitchRoll(0, 0, 0);
            RecalcAABB();
        }

        /// <summary>
        /// Отрисовать без теней
        /// </summary>
        /// <param name="device"></param>
        /// <param name="Camera"></param>
        /// <param name="LightColor"></param>
        /// <param name="LightDirection"></param>
        public void Draw(Device device, EEDCamera Camera, Vector3 LightColor, Vector3 LightDirection)
        {
            Matrix Transform = Conversion.ToMatrix(Transformation * DMatrix.CreateTranslation(-Camera.position));
            MMC.DrawNoShadows(0, Transform, Camera.viewProjectionMatrix, -LightDirection, LightColor);
        }

        /// <summary>
        /// Отрисовать с тенями
        /// </summary>
        /// <param name="device"></param>
        /// <param name="TimeMili"></param>
        /// <param name="Camera"></param>
        /// <param name="LightDirection"></param>
        /// <param name="LightColor"></param>
        /// <param name="S_WVP"></param>
        /// <param name="SplitDistances"></param>
        public void DrawPSSM(Device device, float TimeMili, EEDCamera Camera, Vector3 LightDirection, Vector3 LightColor, Matrix[] S_WVP, float[] SplitDistances)
        {
            Matrix Transform = Conversion.ToMatrix(Transformation * DMatrix.CreateTranslation(-Camera.position));
            MMC.DrawSplitShadows(TimeMili, Transform, Camera.viewProjectionMatrix, -LightDirection, LightColor, S_WVP, SplitDistances);
        }

        /// <summary>
        /// Отрисовать в карту теней
        /// </summary>
        /// <param name="device"></param>
        /// <param name="NewShadowPos"></param>
        /// <param name="LightViewProjMatrix"></param>
        /// <param name="CropMatrices"></param>
        /// <param name="Start"></param>
        /// <param name="Stop"></param>
        public void DrawPSSMSplit(Device device, DVector3 NewShadowPos, Matrix LightViewProjMatrix, Matrix[] CropMatrices, int Start, int Stop)
        {
            Matrix MainWVP = Conversion.ToMatrix(Transformation * DMatrix.CreateTranslation(-NewShadowPos)) * LightViewProjMatrix;
            MMC.DrawSplit(0, MainWVP, CropMatrices, Start, Stop);
        }

        /// <summary>
        /// Отрисовать карту глубины
        /// </summary>
        /// <param name="device"></param>
        /// <param name="Camera"></param>
        public void DrawDepth(Device device, EEDCamera Camera)
        {
            Matrix Transform = Conversion.ToMatrix(Transformation * DMatrix.CreateTranslation(-Camera.position));
            MMC.DrawDepth(0, Transform * Camera.viewProjectionMatrix, Camera);
        }

        public void DrawEffects(Device device, EEDCamera Camera)
        {
            for (int i = 0 ; i < EngPosition.Length; i++)
            {
                DVector3 Pos = DVector3.Transform(EngPosition[i], Transformation);
                LensBatching.DrawLens(Pos, new Vector2(50, 25), new Vector2(0, 0), new Vector2(1, 1), new Vector4(1, 0.5f, 0, 1), Lens);
            }
            
        }

        private void InitObj()
        {
            List<DVector3> LensPos = new List<DVector3> { };
            //HP_MainEngine_v0_2
            for (int i = 0; i < MMC.Hardpoints.Length; i++)
            {
                string name = MMC.Hardpoints[i].HPName;
                name = name.ToLower();
                name = name.TrimStart(new char[] { 'h', 'p', '_' });
                string[] strings = name.Split(new char[] { '_' });
                if (strings.Length > 1)
                {
                    if (strings[0] == "mainengine" && strings[1][0] == 'v')
                    {
                        string num = strings[1].TrimStart(new char[] { 'v' });
                        int NumberEffect = -1;
                        if (Int32.TryParse(num, out NumberEffect))
                        {
                            LensPos.Add(Conversion.ToDoubleVector(MMC.Hardpoints[i].LocalPosition));
                        }
                    }
                    //if (strings[0] == 
                }
            }

            EngPosition = LensPos.ToArray();
        }

        private void RecalcAABB()
        {
            unsafe
            {
                DVector3 v0, v1, v2, v3, v4, v5, v6, v7;
                DVector3 _OAA = LocalAABBMin;
                DVector3 _OBB = LocalAABBMax;
                DMatrix MAT = Transformation;
                SSEmath.SSEmath.ADD_DVectors3_new((uint)&v0, (uint)&v1, (uint)&v2, (uint)&v3, (uint)&v4, (uint)&v5, (uint)&v6, (uint)&v7, (uint)&_OAA, (uint)&_OBB, (uint)&MAT);
                TL[0] = v0;
                TL[1] = v1;
                TL[2] = v2;
                TL[3] = v3;
                TL[4] = v4;
                TL[5] = v5;
                TL[6] = v6;
                TL[7] = v7;
            }
            AABBMax = TL[0];
            AABBMin = TL[0];
            for (int t = 0; t < 8; t++)
            {
                DVector3 V = TL[t];
                if (AABBMax.X < V.X) AABBMax.X = V.X;
                if (AABBMax.Y < V.Y) AABBMax.Y = V.Y;
                if (AABBMax.Z < V.Z) AABBMax.Z = V.Z;

                if (AABBMin.X > V.X) AABBMin.X = V.X;
                if (AABBMin.Y > V.Y) AABBMin.Y = V.Y;
                if (AABBMin.Z > V.Z) AABBMin.Z = V.Z;
            }
        }
    }
}
